package com.atguigu.gmall.common.config;


import com.alibaba.fastjson.JSONObject;
import com.atguigu.gmall.common.entity.GmallCorrelationData;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;

@Component   //实例化
@Slf4j
public class MQProducerAckConfig implements RabbitTemplate.ConfirmCallback,RabbitTemplate.ReturnCallback{

    @Autowired
    private RabbitTemplate rabbitTemplate;
    @Autowired
    private RedisTemplate redisTemplate;

    @PostConstruct  //执行构造器   会执行init初始化方法    如果不打这个注解 是不会执行这个init方法的  原因是这个类添加了Component实例化注解
    public void init(){
        rabbitTemplate.setConfirmCallback(this);
        rabbitTemplate.setReturnCallback(this);
    }


    //交换机应答
    //1. 应答的时机: 成功   失败  都应答
    @Override
    public void confirm(CorrelationData correlationData, boolean ack, String cause) {
        if (ack){
            //成功
            System.out.println("成功应答");
        }else{
            //失败
            System.out.println("失败应答 : 原因是 : " +cause);

            //重新发送消息
            retrySendMessage(correlationData);
        }
    }

    private void retrySendMessage(CorrelationData correlationData) {
        GmallCorrelationData correlationData1= (GmallCorrelationData) correlationData;
        int retryCount = correlationData1.getRetryCount();
        retryCount++;
        correlationData1.setRetryCount(retryCount);
        if (retryCount <= 2){
            //重新发送
            rabbitTemplate.convertAndSend(
                    correlationData1.getExchange(),
                    correlationData1.getRoutingKey(),
                    correlationData1.getMessage(),
                    correlationData1);
            //更新redis中重发消息对象 保存在redis中
            redisTemplate.opsForHash().put("rabbit:prefix:",
                    correlationData1.getId(),
                    JSONObject.toJSONString(correlationData1));
            log.info("成功重新发送 :  " + JSONObject.toJSONString(correlationData1));
        }else{
            log.info("剩余重新发送的次数已经用完 :  "+ JSONObject.toJSONString(correlationData1));
        }

    }

    //队列应答
    //2. 只有失败的时候才会应答
    @Override
    public void returnedMessage(Message message, int replyCode, String replyText, String exchange, String routingKey) {
        System.out.println("msg : " + new String(message.getBody()));
        System.out.println("replyCode : " + replyCode);
        System.out.println("replyText : " + replyText);
        System.out.println("exchange : " + exchange);
        System.out.println("routingKey : " + routingKey);

        Object uuid = message.getMessageProperties().
                getHeader("spring_returned_message_correlation");

        //重新发送  次数
        String rabbit_prefix = (String) redisTemplate.opsForHash().get("rabbit:prefix:", uuid);
        GmallCorrelationData gmallCorrelationData =
                JSONObject.parseObject(rabbit_prefix, GmallCorrelationData.class);
        //判断是否为插件延迟消息
        if (gmallCorrelationData.isDelay()){
            return;
        }

        //重新发送
        //retrySendMessage(gmallCorrelationData);

    }
}
